from django.contrib.auth import get_user_model
from django.contrib.auth.password_validation import validate_password
from django.contrib.auth.hashers import make_password

from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import RefreshToken

from baykeadmin.api.captcha.serializers import (
    CaptchaSerializer, VerifyEmailCodeSerializer
)
from baykeadmin.apps.system.models import BaykeSystemMenu

User = get_user_model()

def get_tokens_for_user(user):
    refresh = RefreshToken.for_user(user)
    return {
        'refresh': str(refresh),
        'access': str(refresh.access_token),
    }


class BaykeSystemLoginSerializer(CaptchaSerializer, TokenObtainPairSerializer):
    pass


class BaykeSystemUserSerializer(serializers.ModelSerializer):
    """用户信息序列化器"""

    class Meta:
        model = User
        fields = ('id', 'username', 'email','is_staff', 'is_active', 'is_superuser', 'groups')


class ChangeEmailSerializer(VerifyEmailCodeSerializer, 
                            serializers.ModelSerializer):
    """ 更新邮箱序列化器 """
    email = serializers.EmailField(
        label="邮箱", 
        required=True, 
        validators=[
            UniqueValidator(
                queryset=User.objects.all(), 
                message="邮箱已存在"
            )
        ])

    class Meta:
        model = User
        fields = ('id', 'email', 'code')

    def validate(self, attrs):
        attrs = super().validate(attrs)
        del attrs['code']
        return attrs
    

class ChangePasswordSerializer(serializers.ModelSerializer):
    """ 更改密码序列化器 """
    old_password = serializers.CharField(label='旧密码', write_only=True)

    class Meta:
        model = User
        fields = ('password', 'old_password')

    def validate(self, attrs):
        user = self.context['request'].user
        if not user.check_password(attrs['old_password']):
            raise serializers.ValidationError('旧密码错误')
        return super().validate(attrs)
    

class RegisterSerializer(VerifyEmailCodeSerializer, serializers.ModelSerializer):
    """ 注册序列化器 """
    email = serializers.EmailField(
        label="邮箱", 
        required=True, 
        validators=[
            UniqueValidator(
                queryset=User.objects.all(), 
                message="邮箱已存在"
            )
        ])
    password1 = serializers.CharField(label='确认密码', write_only=True, style={'input_type': 'password'})
    tokens = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('username', 'password', 'email', 'password1', 'tokens', 'code')
        extra_kwargs = {
            'password': {
                'write_only': True,
                'style': {'input_type': 'password'},
                'label': '密码'
            },
            'username': {
                'help_text': '用户名长度不能小于6位',
                'min_length': 6,
                'label': '用户名'
            },
        }

    def validate(self, attrs):
        if attrs['password'] != attrs['password1']:
            raise serializers.ValidationError('两次密码不一致')
        attrs = super().validate(attrs)
        attrs['password'] = make_password(attrs['password'])
        del attrs['password1']
        del attrs['code']
        return attrs
    
    def validate_password(self, password):
        # 密码强度验证
        validate_password(password)
        return password
    
    def get_tokens(self, obj):  # 获取token
        return get_tokens_for_user(obj)
    


class BaykeSystemMetaSerializer(serializers.Serializer):
    """菜单元信息序列化器
    """
    title = serializers.CharField(label="菜单标题", max_length=30, allow_blank=True)
    icon = serializers.CharField(
        label="图标", 
        max_length=50, 
        allow_blank=True, 
        required=False, 
        default='ant-icon-setting-outlined'
    )
    menu_type = serializers.ChoiceField(
        label="菜单类型", 
        choices=BaykeSystemMenu.MenuType.choices, 
        default=BaykeSystemMenu.MenuType.MENU,
        allow_blank=True
    )
    hidden = serializers.BooleanField(label="是否隐藏", default=False)
    affix = serializers.BooleanField(label="是否固定", default=False)
    hidden_breadcrumb = serializers.BooleanField(label="隐藏面包屑", default=False)
    fullpage = serializers.BooleanField(label="全屏", default=False)
    active = serializers.BooleanField(label="激活", default=False)
    color = serializers.CharField(label="颜色", max_length=50, default='#409EFF')


class BaykeSystemMenuSerializer(serializers.ModelSerializer):
    """菜单序列化器 
    """
    meta = BaykeSystemMetaSerializer(label="菜单元信息", allow_null=True, required=False, many=False)
    children = serializers.SerializerMethodField()

    class Meta:
        model = BaykeSystemMenu
        fields = '__all__'

    def get_children(self, obj):
        return BaykeSystemMenuSerializer(
            obj.baykesystemmenu_set.all(), many=True).data
    
    def create(self, validated_data):
        return super().create(validated_data)
    
    def update(self, instance, validated_data):
        return super().update(instance, validated_data)